/*
 * Copyright (c) 2010, University of Innsbruck, Austria.
 *
 * This library is free software; you can redistribute it and/or modify it under
 * the terms of the GNU Lesser General Public License as published by the Free
 * Software Foundation; either version 2.1 of the License, or (at your option)
 * any later version.
 * This library is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
 * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
 * details.
 * You should have received a copy of the GNU Lesser General Public License along
 * with this library; if not, write to the Free Software Foundation, Inc.,
 * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
 */

package at.sti2.sepn.pattern.network;

import java.util.ArrayList;
import java.util.List;

import at.sti2.sepn.core.triple.RDFTriple;
import at.sti2.sepn.pattern.network.alpha.AlphaMemory;
import at.sti2.sepn.pattern.network.beta.BetaMemory;
import at.sti2.sepn.pattern.network.beta.JoinNode;
import at.sti2.sepn.pattern.network.beta.NegativeJoinResult;
import at.sti2.sepn.pattern.network.beta.NegativeNode;
import at.sti2.sepn.pattern.network.beta.ProductionNode;
import at.sti2.sepn.pattern.network.node.RETENode;
import at.sti2.sepn.pattern.network.node.Token;

public class WorkingMemoryElement {

	private RDFTriple triple = null;
	
	//Added for retracting purposes
	private List <AlphaMemory> alphaMems = null;
	private List <Token> tokens = null;
	
	//Added to support negated conditions
	private List <NegativeJoinResult> negativeJoinResults = null; 

	public WorkingMemoryElement(){
		alphaMems = new ArrayList <AlphaMemory> ();
		tokens = new ArrayList <Token> ();
		negativeJoinResults = new ArrayList <NegativeJoinResult> ();
	}
	
	public WorkingMemoryElement(RDFTriple triple){
		this.triple = triple;
	}
	
	public RDFTriple getTriple() {
		return triple;
	}

	public void setTriple(RDFTriple triple) {
		this.triple = triple;
	}

	public List<AlphaMemory> getAlphaMems() {
		return alphaMems;
	}

	public void setAlphaMems(List<AlphaMemory> alphaMems) {
		this.alphaMems = alphaMems;
	}
	
	public void addAlphaMemory(AlphaMemory alphaMem){
		alphaMems.add(alphaMem);
	}

	public List<Token> getTokens() {
		return tokens;
	}

	public void setTokens(List<Token> tokens) {
		this.tokens = tokens;
	}
	
	public void addToken(Token token){
		tokens.add(token);
	}
	
	public void addNegativeJoinResult(NegativeJoinResult negativeJoinResult){
		negativeJoinResults.add(negativeJoinResult);
	}
	
	public List<NegativeJoinResult> getNegativeJoinResults() {
		return negativeJoinResults;
	}

	public void remove(){
		
		//Remove occurrence from each alpha memory
		for (AlphaMemory alphamem : alphaMems){
			alphamem.removeItem(this);
			
			//If alpha memory just became empty
			if (alphamem.getItems().isEmpty())
				for (RETENode node : alphamem.getSuccessors())
					if (node instanceof JoinNode)
						((JoinNode)node).getParent().getChildren().remove(node);
		}
		
		//Remove all the tokens involving the occurrence of WME
		for (Token token : tokens)
			token.deleteTokenAndDescendents();
		
		for (NegativeJoinResult njr : negativeJoinResults){
			
			njr.getOwner().getNegativeJoinResults().remove(njr);
			
			if (njr.getOwner().getNegativeJoinResults().isEmpty())
				
				for (RETENode node : njr.getOwner().getNode().getChildren())
					if (node instanceof BetaMemory)
						((BetaMemory)node).leftActivate(njr.getOwner(), null);
					else if (node instanceof ProductionNode)
						((ProductionNode)node).leftActivate(njr.getOwner());
					else if (node instanceof NegativeNode)
						((NegativeNode)node).leftActivate(njr.getOwner());
		}
	}
}
